# -*- coding: utf-8 -*-
# @Time    : 2024/7/17 18:04
# @Author  : yujiahao
# @File    : 40_fastapi_sql_crud.py
# @description:SQL (关系型) 数据库  CRUD工具


# 在这个文件中，我们将编写可重用的函数用来与数据库中的数据进行交互。
# CRUD分别为：增加（Create）、查询（Read）、更改（Update）、删除（Delete），即增删改查。
# ...虽然在这个例子中我们只是新增和查询。


import importlib

from sqlalchemy.orm import Session

# from . import models, schemas

# 动态导入
models = importlib.import_module('com.yujiahao.my_fastapi.38_fastapi_sql_models')
schemas = importlib.import_module('com.yujiahao.my_fastapi.39_fastapi_sql_schemas')

# todo 1、读取数据

"""
读取数据：

从 sqlalchemy.orm 中导入 Session，这将允许您声明 db 参数的类型，并在您的函数中进行更好的类型检查和完成。

导入之前的 models（SQLAlchemy 模型）和 schemas（Pydantic 模型/模式）。

创建一些工具函数来完成以下任务：

1. 通过 ID 和电子邮件查询单个用户。
2. 查询多个用户。
3. 查询多个项目。

通过创建仅专用于与数据库交互（获取用户或项目）的函数，独立于路径操作函数，您可以更轻松地在多个部分中重用它们，并为它们添加单元测试。
"""


def get_user(db: Session, user_id: int):
    return db.query(models.User).filter(models.User.id == user_id).first()


# todo 2、读取数据
def get_user_by_email(db: Session, email: str):
    return db.query(models.User).filter(models.User.email == email).first()


# todo 3、读取数据
def get_users(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.User).offset(skip).limit(limit).all()


# todo 1、创建数据
"""
创建数据：

现在创建工具函数来创建数据。

它的步骤是：

1. 使用您的数据创建一个 SQLAlchemy 模型实例。
2. 使用 add 来将该实例对象添加到数据库会话。
3. 使用 commit 来将更改提交到数据库（以便保存它们）。
4. 使用 refresh 来刷新您的实例对象（以便它包含来自数据库的任何新数据，例如生成的 ID）。
"""


def create_user(db: Session, user: schemas.UserCreate):
    fake_hashed_password = user.password + "notreallyhashed"
    db_user = models.User(email=user.email, hashed_password=fake_hashed_password)
    db.add(db_user)
    db.commit()
    db.refresh(db_user)
    return db_user


# todo 4、读取数据
def get_items(db: Session, skip: int = 0, limit: int = 100):
    return db.query(models.Item).offset(skip).limit(limit).all()


# todo 1、创建数据
def create_user_item(db: Session, item: schemas.ItemCreate, user_id: int):
    db_item = models.Item(**item.dict(), owner_id=user_id)
    db.add(db_item)
    db.commit()
    db.refresh(db_item)
    return db_item


"""
Tip:

SQLAlchemy 模型 User 包含一个 hashed_password，它应该是一个包含散列的安全密码。

但由于 API 客户端提供的是原始密码，因此您需要将其提取并在应用程序中生成散列密码。

然后将 hashed_password 参数与要保存的值一起传递。



Warning:

此示例不安全，密码未经过哈希处理。

在现实生活中的应用程序中，您需要对密码进行哈希处理，并且永远不要以明文形式保存它们。

有关更多详细信息，请返回教程中的安全部分。

在这里，我们只关注数据库的工具和机制。



Tip:

这里不是将每个关键字参数传递给 Item 并从 Pydantic 模型中读取每个参数，而是先生成一个字典，其中包含 Pydantic 模型的数据：

    item.dict()

然后我们将 dict 的键值对作为关键字参数传递给 SQLAlchemy Item：

    Item(**item.dict())

然后我们传递 Pydantic 模型未提供的额外关键字参数 owner_id：

    Item(**item.dict(), owner_id=user_id)
"""
